import { Context, Schema, Session } from 'koishi'
import { status, statusBedrock } from 'minecraft-server-util';
import { resolve } from 'path'

export const name = 'mcserver-query'


export const SEND_FORMAT = {
  TEXT_WITH_IMAGE: '文字+图片 Text with Image',
  // IMAGE: '图片image todo',
  FORWARD: '转发消息 Forward Message'
} as const;

export const JAVA_SERVER_INFO = {
  STATUS: '服务器状态 Server Status',
  MOTD: '服务器描述 MOTD',
  VERSION: '服务器版本 Version',
  PLAYERS_COUNT: '玩家数量 Players Count',
  PING: '延迟 Ping',
  PLAYERS_ONLINE: '在线玩家列表 Online Players',
} as const;

export const BEDROCK_SERVER_INFO = {
  STATUS: '服务器状态 Server Status',
  MOTD: '服务器描述 MOTD',
  VERSION: '服务器版本 Version',
  PLAYERS_COUNT: '玩家数量 Players Count',
  GAME_MODE: '游戏模式 Game Mode',
  SERVER_ID: '服务器ID Server ID',
} as const;



export interface Config {
  defaultServerArgList: {
    ip: string;
    port: number;
    java: boolean;
  }[];

  text_with_image_hint: string;
  image_hint: string;
  forward_hint: string;

  sendFormatSeq: {
    format: (typeof SEND_FORMAT)[keyof typeof SEND_FORMAT];
    ifReply: boolean;
  }[];

  JavaServerContentSeq: {
    enabled: boolean;
    entry: (typeof JAVA_SERVER_INFO)[keyof typeof JAVA_SERVER_INFO];
  }[];

  BedrockServerContentSeq: {
    enabled: boolean;
    entry: (typeof BEDROCK_SERVER_INFO)[keyof typeof BEDROCK_SERVER_INFO];
  }[];

}

export const Config: Schema<Config> = Schema.intersect([
  Schema.object({

    defaultServerArgList: Schema.array(
      Schema.object({
        ip: Schema.string().role('link'),
        port: Schema.number().min(0).max(65535).step(1),
        java: Schema.boolean(),
      })
    )
      .role('table')
      .default([
        { ip: 'whzz.online', port: 25579, java: true, },
        { ip: 'mc.hypixel.net', port: 25565, java: true, },
      ]),
  }),

  Schema.object({
    text_with_image_hint: Schema.string().default('Note备注').disabled(),
    image_hint: Schema.string().default('Note备注').disabled(),
    forward_hint: Schema.string().default('Note备注').disabled(),

    sendFormatSeq: Schema.array(
      Schema.object({
        format: Schema.union([SEND_FORMAT.TEXT_WITH_IMAGE, SEND_FORMAT.FORWARD]),
        ifReply: Schema.boolean(),
      })
    )
      .role('table')
      .default([
        { ifReply: true, format: SEND_FORMAT.TEXT_WITH_IMAGE, },
        { ifReply: false, format: SEND_FORMAT.FORWARD, }
      ]),

    JavaServerContentSeq: Schema.array(
      Schema.object({
        enabled: Schema.boolean(),
        entry: Schema.union([JAVA_SERVER_INFO.STATUS, JAVA_SERVER_INFO.MOTD, JAVA_SERVER_INFO.VERSION, JAVA_SERVER_INFO.PLAYERS_COUNT, JAVA_SERVER_INFO.PING, JAVA_SERVER_INFO.PLAYERS_ONLINE]),
      })
    )
      .role('table')
      .default([
        { enabled: true, entry: JAVA_SERVER_INFO.STATUS, },
        { enabled: true, entry: JAVA_SERVER_INFO.MOTD, },
        { enabled: true, entry: JAVA_SERVER_INFO.VERSION, },
        { enabled: true, entry: JAVA_SERVER_INFO.PLAYERS_COUNT, },
        { enabled: true, entry: JAVA_SERVER_INFO.PING, },
        { enabled: true, entry: JAVA_SERVER_INFO.PLAYERS_ONLINE, },
      ]), 

    BedrockServerContentSeq: Schema.array(
      Schema.object({
        enabled: Schema.boolean(),
        entry: Schema.union([BEDROCK_SERVER_INFO.STATUS, BEDROCK_SERVER_INFO.MOTD, BEDROCK_SERVER_INFO.VERSION, BEDROCK_SERVER_INFO.PLAYERS_COUNT, BEDROCK_SERVER_INFO.GAME_MODE, BEDROCK_SERVER_INFO.SERVER_ID]),
      })
    )
      .role('table')
      .default([
        { enabled: true, entry: BEDROCK_SERVER_INFO.STATUS, },
        { enabled: true, entry: BEDROCK_SERVER_INFO.MOTD, },
        { enabled: true, entry: BEDROCK_SERVER_INFO.VERSION, },
        { enabled: true, entry: BEDROCK_SERVER_INFO.PLAYERS_COUNT, },
        { enabled: true, entry: BEDROCK_SERVER_INFO.GAME_MODE, },
        { enabled: true, entry: BEDROCK_SERVER_INFO.SERVER_ID, },
      ]),
    



  })



]).i18n({
  'zh-CN': require('./locales/zh-CN')._config,
  'en-US': require('./locales/en-US')._config,
})


export function apply(ctx: Context, config: Config) {
  // 加载本地化文件
  ctx.i18n.define('zh-CN', require('./locales/zh-CN.yml'))
  ctx.i18n.define('en-US', require('./locales/en-US.yml'))

  ctx.command('mcstatus <host:string> <port:number>', 'commands.mcstatus.description')
    .usage('commands.mcstatus.usage')
    .option('bedrock', '-b commands.mcstatus.options.bedrock')
    .option('timeout', '-t <timeout:number> commands.mcstatus.options.timeout', { fallback: 5000 })
    .action(async ({ session, options }, host, port) => {
      // 如果没有传入 host，使用配置中的默认服务器
      if (!host) {
        if (!config.defaultServerArgList || config.defaultServerArgList.length === 0) {
          return session.text('commands.mcstatus.messages.no-default-server');
        }
        const defaultServer = config.defaultServerArgList[0];
        host = defaultServer.ip;
        port = port || defaultServer.port;
        options.bedrock = !defaultServer.java;
      }

      const serverPort = port ? port : (options.bedrock ? 19132 : 25565);
      
      try {
         if ( !options.bedrock ) {
          // Query Java server
          const response = await status(host, serverPort, { timeout: options.timeout })
          
          let statusLines: string[] = [];
          for (const item of config.JavaServerContentSeq) {
            if ( !item.enabled ) continue;
            // console.log("qwq");
            if ( item.entry === JAVA_SERVER_INFO.STATUS )
              statusLines.push(session.text('commands.mcstatus.messages.java-status', [host, serverPort]));
            else if ( item.entry === JAVA_SERVER_INFO.MOTD )
              statusLines.push(session.text('commands.mcstatus.messages.motd', [response.motd.clean]));
            else if ( item.entry === JAVA_SERVER_INFO.VERSION )
              statusLines.push(session.text('commands.mcstatus.messages.version', [response.version.name]));
            else if ( item.entry === JAVA_SERVER_INFO.PLAYERS_COUNT )
              statusLines.push(session.text('commands.mcstatus.messages.players', [response.players.online, response.players.max]));
            else if ( item.entry === JAVA_SERVER_INFO.PING )
              statusLines.push(session.text('commands.mcstatus.messages.ping', [response.roundTripLatency]));
            else if ( item.entry === JAVA_SERVER_INFO.PLAYERS_ONLINE ) {
              // 处理在线玩家列表
              if (response.players.sample && response.players.sample.length > 0) {
                const playerList = response.players.sample.slice(0, 10).map(p => p.name).join(', ');
                statusLines.push(session.text('commands.mcstatus.messages.players-online', [playerList]));
              } else if (response.players.online > 0) {
                // 有玩家在线但服务器不提供玩家列表
                statusLines.push(session.text('commands.mcstatus.messages.players-online-no-list', [response.players.online]));
              } else {
                // 没有玩家在线
                statusLines.push(session.text('commands.mcstatus.messages.no-players'));
              }
            }
          }
          
          await session.send(statusLines.join('\n'));
          return;
        } else {
          // Query Bedrock server
          const response = await statusBedrock(host, serverPort, { timeout: options.timeout })

          let statusLines: string[] = [];
          for (const item of config.BedrockServerContentSeq) {
            if ( !item.enabled ) continue;
            // console.log("qwq");
            if ( item.entry === BEDROCK_SERVER_INFO.STATUS )
              statusLines.push(session.text('commands.mcstatus.messages.bedrock-status', [host, serverPort]));
            else if ( item.entry === BEDROCK_SERVER_INFO.MOTD )
              statusLines.push(session.text('commands.mcstatus.messages.motd', [response.motd.clean]));
            else if ( item.entry === BEDROCK_SERVER_INFO.VERSION )
              statusLines.push(session.text('commands.mcstatus.messages.version', [response.version.name]));
            else if ( item.entry === BEDROCK_SERVER_INFO.PLAYERS_COUNT )
              statusLines.push(session.text('commands.mcstatus.messages.players', [response.players.online, response.players.max]));
            else if ( item.entry === BEDROCK_SERVER_INFO.GAME_MODE )
              statusLines.push(session.text('commands.mcstatus.messages.game-mode', [response.gameMode]));
            else if ( item.entry === BEDROCK_SERVER_INFO.SERVER_ID )
              statusLines.push(session.text('commands.mcstatus.messages.server-id', [response.serverID]));
          }

          await session.send(statusLines.join('\n'));
          return;
        }
      } catch (error) {
        return [
          session.text('commands.mcstatus.messages.query-failed', [host, serverPort]),
          session.text('commands.mcstatus.messages.error', [error.message])
        ].join('\n')
      }
    })

  ctx.command('mcping [host] [port]', 'commands.mcping.description')
    .usage('commands.mcping.usage')
    .option('bedrock', '-b commands.mcping.options.bedrock')
    .option('timeout', '-t <timeout:number> commands.mcping.options.timeout', { fallback: 3000 })
    .action(async ({ session, options }, host, port) => {
      // 如果没有传入 host，使用配置中的默认服务器
      if (!host) {
        if (!config.defaultServerArgList || config.defaultServerArgList.length === 0) {
          return session.text('commands.mcping.messages.no-default-server')
        }
        const defaultServer = config.defaultServerArgList[0]
        host = defaultServer.ip
        port = port || defaultServer.port.toString()
        options.bedrock = !defaultServer.java
      }

      const serverPort = port ? parseInt(port) : (options.bedrock ? 19132 : 25565)
      
      try {
        const startTime = Date.now()
        
        if (options.bedrock) {
          await statusBedrock(host, serverPort, { timeout: options.timeout })
        } else {
          await status(host, serverPort, { timeout: options.timeout })
        }
        
        const pingTime = Date.now() - startTime
        return session.text('commands.mcping.messages.online', [host, serverPort, pingTime])
      } catch (error) {
        return [
          session.text('commands.mcping.messages.offline', [host, serverPort]),
          session.text('commands.mcping.messages.error', [error.message])
        ].join('\n')
      }
    })

}
